package com.company.genealogy.common.util;

import com.company.genealogy.common.constant.JwtConstants;
import io.jsonwebtoken.*;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 * 提供JWT token的生成、解析、验证等功能。
 * 支持访问token和刷新token的生成和管理。
 * @author chenzhixiang
 */
@Component
public class JwtUtil {

    @Value("${jwt.secret:defaultSecretKey}")
    private String secret;

    /**
     * -- GETTER --
     *  获取访问token过期时间（秒）
     *
     * @return 过期时间
     */
    @Getter
    @Value("${jwt.access-token.expiration:3600}")
    private long accessTokenExpiration;

    /**
     * -- GETTER --
     *  获取刷新token过期时间（秒）
     *
     * @return 过期时间
     */
    @Getter
    @Value("${jwt.refresh-token.expiration:604800}")
    private long refreshTokenExpiration;

    /**
     * 处理Authorization头，提取token
     * 
     * @param authorization Authorization头
     * @return 提取的token，如果格式不正确返回null
     */
    public String extractTokenFromAuthorization(String authorization) {
        if (!StringUtils.hasText(authorization)) {
            return null;
        }
        
        if (authorization.startsWith("Bearer ")) {
            return authorization.substring(7);
        }
        
        return authorization;
    }

    /**
     * 生成访问token
     * 
     * @param userId 用户ID
     * @param username 用户名
     * @param userType 用户类型
     * @param clanId 家族ID
     * @param branchId 分支ID
     * @param memberId 成员ID
     * @param authorities 权限列表
     * @return 访问token
     */
    public String generateAccessToken(Long userId, String username, String userType, 
                                   Long clanId, Long branchId, Long memberId, String authorities) {
        return generateToken(userId, username, userType, clanId, branchId, memberId, 
                           authorities, accessTokenExpiration * 1000);
    }

    /**
     * 生成刷新token
     * 
     * @param userId 用户ID
     * @param username 用户名
     * @return 刷新token
     */
    public String generateRefreshToken(Long userId, String username) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtConstants.CLAIM_USER_ID, userId);
        claims.put(JwtConstants.CLAIM_USERNAME, username);
        
        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + refreshTokenExpiration * 1000))
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

    /**
     * 生成token的通用方法
     * 
     * @param userId 用户ID
     * @param username 用户名
     * @param userType 用户类型
     * @param clanId 家族ID
     * @param branchId 分支ID
     * @param memberId 成员ID
     * @param authorities 权限列表
     * @param expiration 过期时间（毫秒）
     * @return token字符串
     */
    private String generateToken(Long userId, String username, String userType, 
                               Long clanId, Long branchId, Long memberId, 
                               String authorities, long expiration) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtConstants.CLAIM_USER_ID, userId);
        claims.put(JwtConstants.CLAIM_USERNAME, username);
        claims.put(JwtConstants.CLAIM_USER_TYPE, userType);
        claims.put(JwtConstants.CLAIM_CLAN_ID, clanId);
        claims.put(JwtConstants.CLAIM_BRANCH_ID, branchId);
        claims.put(JwtConstants.CLAIM_MEMBER_ID, memberId);
        claims.put(JwtConstants.CLAIM_AUTHORITIES, authorities);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

    /**
     * 从token中获取用户ID
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 用户ID
     */
    public Long getUserIdFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_USER_ID, Long.class);
    }

    /**
     * 从token中获取用户名
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 用户名
     */
    public String getUsernameFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_USERNAME, String.class);
    }

    /**
     * 从token中获取用户类型
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 用户类型
     */
    public String getUserTypeFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_USER_TYPE, String.class);
    }

    /**
     * 从token中获取家族ID
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 家族ID
     */
    public Long getClanIdFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_CLAN_ID, Long.class);
    }

    /**
     * 从token中获取分支ID
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 分支ID
     */
    public Long getBranchIdFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_BRANCH_ID, Long.class);
    }

    /**
     * 从token中获取成员ID
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 成员ID
     */
    public Long getMemberIdFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_MEMBER_ID, Long.class);
    }

    /**
     * 从token中获取权限列表
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 权限列表字符串
     */
    public String getAuthoritiesFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.get(JwtConstants.CLAIM_AUTHORITIES, String.class);
    }

    /**
     * 获取token的过期时间
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return 过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        String cleanToken = extractTokenFromAuthorization(token);
        if (cleanToken == null) {
            return null;
        }
        Claims claims = getClaimsFromToken(cleanToken);
        return claims.getExpiration();
    }

    /**
     * 验证token是否过期
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return true-已过期，false-未过期
     */
    public boolean isTokenExpired(String token) {
        try {
            String cleanToken = extractTokenFromAuthorization(token);
            if (cleanToken == null) {
                return true;
            }
            Date expiration = getExpirationDateFromToken(cleanToken);
            return expiration.before(new Date());
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 验证token是否有效
     * 
     * @param token JWT token（支持带Bearer前缀）
     * @return true-有效，false-无效
     */
    public boolean validateToken(String token) {
        try {
            String cleanToken = extractTokenFromAuthorization(token);
            if (cleanToken == null) {
                return false;
            }
            Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(cleanToken);
            return !isTokenExpired(cleanToken);
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 从token中解析Claims
     * 
     * @param token JWT token
     * @return Claims对象
     */
    private Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

}